package com.catazzz.mall.mbg;

import lombok.extern.slf4j.Slf4j;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.internal.DefaultCommentGenerator;
import org.mybatis.generator.internal.util.StringUtility;

import java.util.Properties;

/**
 * @作者: Tao
 * @日期: 2025/1/17
 * @时间: 12:14
 * @描述: 自定义注释生成器 <br><pre>
 *     生成实体类时，为字段添加注释
 */
@Slf4j
public class CommentGenerator extends DefaultCommentGenerator {

    // 控制是否添加备注评论的标志
    private boolean addRemarkComments = false;

    private static final String EXAMPLE_SUFFIX = "Example";
    private static final String MAPPER_SUFFIX = "Mapper";
    private static final String MODEL_PACKAGE_NAME = "com.catazzz.mall.mbg.model";
    private static final String API_MODEL_PROPERTY_FULL_CLASS_NAME = "io.swagger.annotations.ApiModelProperty";

    /**
     * 添加配置属性，以控制是否需要生成备注信息
     *
     * @param properties 包含配置信息的属性集，包括是否添加备注评论的配置
     */
    @Override
    public void addConfigurationProperties(Properties properties) {
        super.addConfigurationProperties(properties);
        // 根据配置信息设置是否添加备注评论
        this.addRemarkComments = StringUtility.isTrue(properties.getProperty("addRemarkComments"));
    }

    /**
     * 为字段添加注释
     * 仅当配置为需要添加备注信息，且字段的备注信息非空时，才添加JavaDoc
     *
     * @param field              要添加注释的字段
     * @param introspectedTable  表信息对象，包含表的结构信息
     * @param introspectedColumn 列信息对象，包含字段的结构信息和备注
     */
    @Override
    public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
        String remarks = introspectedColumn.getRemarks();
        //根据参数和备注信息判断是否添加备注信息
        if (addRemarkComments && StringUtility.stringHasValue(remarks)) {
//            addFieldJavaDoc(field, remarks);
            // 数据库特殊字符转义，替换双引号为单引号，防止编译报错
            if (remarks.contains("\"")) {
                remarks = remarks.replace("\"", "'");
            }
            // 添加swagger的ApiModelProperty注解
            field.addJavaDocLine("@ApiModelProperty(value = \"" + remarks + "\")");
        }
    }

    /**
     * 为字段添加JavaDoc注释
     * 注释内容为数据库字段的备注信息
     *
     * @param field   要添加JavaDoc的字段
     * @param remarks 数据库字段的备注信息
     */
    private void addFieldJavaDoc(Field field, String remarks) {
        //文档注释开始
        field.addJavaDocLine("/**");
        //获取数据库字段的备注信息
        String[] remarkLines = remarks.split(System.lineSeparator());
        for (String remarkLine : remarkLines) {
            field.addJavaDocLine(" * " + remarkLine);
        }
        addJavadocTag(field, false);
        // 文档注释结束
        field.addJavaDocLine(" */");
    }

    /**
     * 为Java文件添加注释
     * 此方法用于在编译单元中添加特定的导入类型，仅当编译单元对应的类型是Mapper的一部分且不是Example的一部分时执行
     * 这是为了确保只有在处理Mapper相关代码时，才会添加API模型属性的完全限定类名作为导入类型
     *
     * @param compilationUnit 编译单元，代表当前正在处理的Java文件
     */
    @Override
    public void addJavaFileComment(CompilationUnit compilationUnit) {
        // 调用父类的同名方法，执行通用的添加注释逻辑
        super.addJavaFileComment(compilationUnit);

        // 检查当前编译单元是否是Mapper的一部分且不是Example的一部分
        log.info("compilationUnit.getPackageName().() = {}", compilationUnit.getType().getPackageName());
        if (compilationUnit.getType().getFullyQualifiedName().contains(MODEL_PACKAGE_NAME) && !compilationUnit.getType().getFullyQualifiedName().contains(EXAMPLE_SUFFIX)) {
            // 如果条件满足，则向编译单元中添加API模型属性的完全限定类名作为导入类型
            compilationUnit.addImportedType(new FullyQualifiedJavaType(API_MODEL_PROPERTY_FULL_CLASS_NAME));
        }
    }
}

